﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Universe.OneC.DomainModel;

namespace Universe.OneC
{
    public partial class OneCReader
    {
        private Adapter1C _adapter;
        private MetaModel _model;

        public OneCReader(Adapter1C adapter, MetaModel model)
        {
            _adapter = adapter;
            _model = model;
        }

        public Adapter1C Adapter
        {
            get { return _adapter; }
        }

        public MetaModel Model
        {
            get { return _model; }
        }

        public Dump1C ReadDocumentOrCatalog(MetaClass meta)
        {
            string managerPrefix =
                meta.GetGroup2() == MetaClassGroup.Catalog
                    ? "Справочник"
                    : meta.GetGroup2() == MetaClassGroup.Document
                          ? "Документ"
                          : "";
                              
            using (ObjectsCache objects = new ObjectsCache(Adapter))
            {
                List<MetaClass> metaParts = meta.Model.GetTableParts(meta);
                object manager = Adapter.NewObject(managerPrefix + "Менеджер." + meta.Name);
                object selection = manager.Call("Select");
                Dump1C ret = new Dump1C();
                int rowNumber = 0;
                int errorCount = 0;
                while (true)
                {
                    bool areMore = (bool)selection.Call("Next");
                    if (!areMore)
                        break;

                    // object row = selection.Call("GetObject");
                    Row1C dataRow = new Row1C();

                    foreach (MetaProperty property in meta.GetProperties())
                    {
                        object value = null;
                        string propertyName = property.Name;
                        string cellAddress = string.Format("{0}[{1},{2}]", meta.Name, rowNumber, propertyName);
                        PropertyValue propertyValue = null;
                        try
                        {
                            value = selection.Get(propertyName);
                            propertyValue = GetPropertyValue(value, objects);
                        }
                        catch (Exception ex)
                        {
                            propertyValue = new FailedPropertyValue();
                            Debug.WriteLine(" Read " + cellAddress + " error " + Environment.NewLine + ex);
                            errorCount++;
                        }

                        dataRow.Cells.Add(property.Name, propertyValue);
                        value.ReleaseComObject();
                        Debug.WriteLine(cellAddress + ": " + propertyValue.ToDumpString());
                    }



                    foreach (MetaClass tablePart in metaParts)
                    {
                        PropertyOfTablePart ptp =
                            new PropertyOfTablePart
                                {
                                    HasValue = true,
                                    Type1C = string.Empty,
                                    Rows = new List<RowOfTable1C>()
                                };

                        object rawTablePart = selection.Get(tablePart.Name);
                        int countTablePart = (int)rawTablePart.Call("Count");
                        Debug.WriteLine(string.Format(" Table Part: " + tablePart.Name + " COUNT is " + countTablePart));
                        for (int it = 0; it < countTablePart; it++)
                        {
                            RowOfTable1C row = new RowOfTable1C() {RowNumber = it + 1};
                            object tablePartRow = rawTablePart.Call("Get", it);
                            foreach (MetaProperty partProperty in tablePart.GetProperties())
                            {
                                string cellAddres = string.Format(
                                    "{0}[{1},{2}]", tablePart.Name, it, partProperty.Name);

                                object partValue = null;
                                PropertyValue partPropertyValue;
                                try
                                {
                                    partValue = tablePartRow.Get(partProperty.Name);
                                    partPropertyValue = GetPropertyValue(partValue, objects);
                                }
                                catch (Exception ex)
                                {
                                    partPropertyValue = new FailedPropertyValue();
                                    Debug.WriteLine("     Read " + cellAddres + " error " + Environment.NewLine + ex);
                                    throw;
                                }

                                row.Cells.Add(partProperty.Name, partPropertyValue);
                                partValue.ReleaseComObject();
                                Debug.WriteLine("    " + cellAddres + ": " + partPropertyValue.ToDumpString());

                            }

                            ptp.Rows.Add(row);

                            tablePartRow.ReleaseComObject();


                        }

                        dataRow.Cells.Add(tablePart.Name, ptp);


                        rawTablePart.ReleaseComObject();
                    }

                    rowNumber++;
                    ret.ResultSet.Add(dataRow);
                    // row.ReleaseComObject();
                }

                selection.ReleaseComObject();
                manager.ReleaseComObject();
                if (errorCount > 0)
                    Debug.WriteLine("ERRORS on [" + meta.Name + "] COUNT IS " + errorCount);

                Debug.WriteLine("");
                return ret;
            }
        }
        
        [Obsolete("", true)]
        public Dump1C ReadCatalog(MetaClass catalog)
        {

            using (ObjectsCache objects = new ObjectsCache(Adapter))
            {

                List<MetaClass> metaParts = catalog.Model.GetTableParts(catalog);
                object manager = Adapter.NewObject("СправочникМенеджер." + catalog.Name);
                object selection = manager.Call("Select");
                Dump1C ret = new Dump1C();
                int rowNumber = 0;
                int errorCount = 0;
                while (true)
                {
                    bool areMore = (bool) selection.Call("Next");
                    if (!areMore)
                        break;

                    // object row = selection.Call("GetObject");
                    Row1C dataRow = new Row1C();

                    foreach (MetaProperty property in catalog.GetProperties())
                    {
                        object value = null;
                        string propertyName = property.Name;
                        string cellAddress = string.Format("{0}[{1},{2}]", catalog.Name, rowNumber, propertyName);
                        PropertyValue propertyValue = null;
                        try
                        {
                            value = selection.Get(propertyName);
                            propertyValue = GetPropertyValue(value, objects);
                        }
                        catch (Exception ex)
                        {
                            propertyValue = new FailedPropertyValue();
                            Debug.WriteLine(" Read " + cellAddress + " error " + Environment.NewLine + ex);
                            errorCount++;
                        }

                        dataRow.Cells.Add(propertyName, propertyValue);

                        value.ReleaseComObject();
                        Debug.WriteLine(cellAddress + ": " + propertyValue.ToDumpString());
                    }



                    foreach (MetaClass tablePart in metaParts)
                    {
                        PropertyOfTablePart ptp = new PropertyOfTablePart
                                                      {
                                                          HasValue = true,
                                                          Type1C = string.Empty,
                                                          Rows = new List<RowOfTable1C>()
                                                      };

                        object rawTablePart = selection.Get(tablePart.Name);
                        int countTablePart = (int) rawTablePart.Call("Count");
                        Debug.WriteLine(string.Format(" Table Part: " + tablePart.Name + " COUNT is " + countTablePart));
                        for (int it = 0; it < countTablePart; it++)
                        {
                            RowOfTable1C row = new RowOfTable1C {RowNumber = it + 1};
                            object tablePartRow = rawTablePart.Call("Get", it);
                            foreach (MetaProperty partProperty in tablePart.GetProperties())
                            {
                                string cellAddres = string.Format(
                                    "{0}[{1},{2}]", tablePart.Name, it, partProperty.Name);

                                object partValue;
                                PropertyValue partPropertyValue;
                                try
                                {
                                    partValue = tablePartRow.Get(partProperty.Name);
                                    partPropertyValue = GetPropertyValue(partValue, objects);
                                }
                                catch (Exception ex)
                                {
                                    partPropertyValue = new FailedPropertyValue();
                                    Debug.WriteLine("     Read " + cellAddres + " error " + Environment.NewLine + ex);
                                    throw;
                                }

                                row.Cells.Add(partProperty.Name, partPropertyValue);

                                partValue.ReleaseComObject();
                                Debug.WriteLine("    " + cellAddres + ": " + partPropertyValue.ToDumpString());
                            }

                            ptp.Rows.Add(row);

                            tablePartRow.ReleaseComObject();
                        }

                        rawTablePart.ReleaseComObject();
                    }

                    rowNumber++;
                    ret.ResultSet.Add(dataRow);
                    // row.ReleaseComObject();
                }

                selection.ReleaseComObject();
                manager.ReleaseComObject();
                if (errorCount > 0)
                    Debug.WriteLine("ERRORS on [" + catalog.Name + "] COUNT IS " + errorCount);

                Debug.WriteLine("");
                return ret;
            }
        }

    }
}
